/* eslint-disable no-case-declarations */
/* eslint-disable no-unused-vars */

/** 将Oracle返回的 20190203 格式的生日字符串格式化成自定义的字符串
 * @param {String} birthdayString Oracle返回的 20190203 格式的时间字符串
 * @returns {String} 自定义格式的时间字符串
 */
export function getAge(birthdayString) {
  const year = birthdayString.substring(0, 4)
  const month = birthdayString.substring(4, 6)
  const day = birthdayString.substring(6, 8)
  const dateString = year + '-' + month + '-' + day
  const age = parseAge(dateString)
  return dateString + ' (' + age + ' 岁)'
}

/** 根据 yyyy-MM-dd 格式的 String 类型的出生年月日字符串计算年龄
 * @param {String} birthdayString  yyyy-MM-dd 格式的生日字符串
 * @returns {String} 年龄字符串
 */
export function parseAge(birthdayString) {
  if (!birthdayString || birthdayString === '') return 0
  let age = 0
  // 获取出生日期的年月日
  const year = parseInt(getYMD(birthdayString, 'y'))
  const month = parseInt(getYMD(birthdayString, 'm'))
  const day = parseInt(getYMD(birthdayString, 'd'))
  // 获取当前时间的年月日
  const now = new Date()
  const nowYear = now.getFullYear()
  const nowMonth = now.getMonth() + 1
  const nowDay = now.getDate()
  if (nowYear <= year) return 0
  age = nowYear - year - 1
  if (nowMonth > month) {
    age++
  } else if (nowMonth === month) {
    if (nowDay >= day) {
      age++
    }
  }
  return age
}

/** 检查日期时间格式的字符串是否正确
 * @param {String} strSource 要检查的字符串
 * @returns {Boolean} 是否是日期时间的正确格式
 */
export function isDTStr(strSource) {
  try {
    return new Date(strSource) !== null
  } catch {
    return false
  }
}

/** 后端输出LocalDateTime格式的时间是 2021-11-02T17:29:02
 */
export function formatLDT(ldtString) {
  if (!ldtString || ldtString === '') {
    return ''
  }
  return ldtString.replace(/T/g, ' ')
}

// ================ Date、Number、String 三种时间格式互转

/** Date 转 成13位的int
 * @param {Date} Date格式的值
 * @return {Number} 转换后的Number类型的时间戳
 */
export function date2Int(date) {
  return new Date(date).getTime()
}

// 指定日期时间格式的字符串转成13位的int
export function str2Int(dtString, formatIn) {
  let dtTemp = str2Date(dtString, formatIn)
  return dtTemp === null ? date2Int(dtTemp) : 0
}

/** 将指定格式的字符串转成Date对象，如果只有时间，日期默认为 2000-1-1
 * @param {String} strSource 要转换的字符串
 * @param {String} formatString 要转换的字符串的格式
 * @return {Date} Date对象，如果字符串格式不正确，输出null
 */
export function str2Date(strSource, formatString) {
  if (!strSource) return null
  if (!formatString || formatString === '') return null
  let strTemp, aryTemp, year, month, day, hour, minute, second
  // formatString 支持如下格式
  // substring(startIndex, endIndex) 子串包括 开始 处的字符
  // 但不包括 结束 处的字符，即到前面一个字符串结束
  switch (formatString) {
    case 'yyyyMM':
      // yyyyMM 198610
      if (!strSource || strSource.length !== 6) {
        return null
      }
      year = strSource.substring(0, 4)
      month = strSource.substring(4, 6)
      day = 1
      hour = 0
      minute = 0
      second = 0
      break
    case 'yyyyMMdd':
      // yyyyMMdd 20221025
      if (!strSource || strSource.length !== 8) {
        return null
      }
      year = strSource.substring(0, 4)
      month = strSource.substring(4, 6)
      day = strSource.substring(6)
      hour = 0
      minute = 0
      second = 0
      break
    case 'yyyy/MM/dd':
      // yyyy/MM/dd 2022/10/25
      if (!strSource || strSource.length !== 10) {
        return null
      }
      aryTemp = strSource.split('/')
      if (aryTemp.length !== 3) {
        return null
      }
      // 去除中间 /
      strTemp = strSource.replace(/\//g, '')
      year = strTemp.substring(0, 4)
      month = strTemp.substring(4, 6)
      day = strTemp.substring(6)
      hour = 0
      minute = 0
      second = 0
      break
    case 'yyyy-MM-dd':
      // yyyy-MM-dd 2022-10-25
      if (!strSource || strSource.length !== 10) {
        return null
      }
      aryTemp = strSource.split('-')
      if (aryTemp.length !== 3) {
        return null
      }
      // 去除中间 -
      strTemp = strSource.replace(/-/g, '')
      year = strTemp.substring(0, 4)
      month = strTemp.substring(4, 6)
      day = strTemp.substring(6)
      hour = 0
      minute = 0
      second = 0
      break
    case 'HH:mm:ss':
      // HH:mm:ss 21:54:32
      if (!strSource || strSource.length !== 8) {
        return null
      }
      aryTemp = strSource.split(':')
      if (aryTemp.length !== 3) {
        return null
      }
      // 去除中间 :
      strTemp = strSource.replace(/:/g, '')
      year = 2000
      month = 1
      day = 1
      hour = strTemp.substring(0, 2)
      minute = strTemp.substring(2, 4)
      second = strTemp.substring(4)
      break
    case 'yyyy-MM-dd HH:mm:ss':
      strTemp = strSource.replace(/-/g, '/')
      // yyyy-MM-dd HH:mm:ss 2022-10-25 21:54:32
      return isDTStr(strTemp) ? new Date(strTemp) : null
    case 'yyyy/MM/dd HH:mm:ss':
      // yyyy/MM/dd HH:mm:ss 2022/10/25 21:54:32
      return isDTStr(strSource) ? new Date(strSource) : null
    case 'LDT':
      // LDT (yyyy-MM-ddTHH:mm:ss) 2022-10-25T21:54:32
      strTemp = strSource.replace(/T/g, ' ')
      return isDTStr(strTemp) ? new Date(strSource) : null
    default:
      return null
  }
  strTemp = year + '/' + month + '/' + day + ' ' + hour + ':' + minute + ':' + second
  if (isDTStr()) {
    return new Date(strTemp)
  } else {
    return null
  }
}

export function str2Str(strSource, formatIn, formatOut) {
  return obj2Str(str2Date(strSource, formatIn), formatOut)
}

export function int2Date(dt) {
  if ((dt + '').length === 10) dt = dt * 1000
  return new Date(dt)
}

/** Date 类型、Number 类型的 dt 转成指定格式的字符串
 * @param {(Object|String|Number)} dt 要装换的入参
 * @param {String} formatString 表示返回的日期字符串的格式，默认为 {y}-{m}-{d} {h}:{i}:{s}
 * @returns {String} 以指定格式返回的日期时间字符串
 */
export function obj2Str(dt, formatOut) {
  // console.log('obj2Str:', dt)
  if (!dt) return ''
  // 将 dt 入参统一成 Date 格式
  let dtTemp
  if (typeof dt === 'object') {
    // 如果入参是 Date 数据类型
    dtTemp = dt
  } else if (typeof dt === 'number') {
    // 如果入参是 Number 数据类型
    dtTemp = int2Date(dt)
  } else return ''

  if (!formatOut || formatOut === '') {
    formatOut = '{y}-{m}-{d} {h}:{i}:{s}'
  }
  // 按照指定格式输出
  const formatObj = {
    y: dtTemp.getFullYear(),
    m: dtTemp.getMonth() + 1,
    d: dtTemp.getDate(),
    h: dtTemp.getHours(),
    i: dtTemp.getMinutes(),
    s: dtTemp.getSeconds(),
    // getDay() 返回值为 0 是表示周日(Sunday)
    w: dtTemp.getDay(),
  }
  const resultString = formatOut.replace(/{(y|m|d|h|i|s|w)+}/g, (result, key) => {
    let value = formatObj[key]
    if (key === 'w') {
      return ['周日', '周一', '周二', '周三', '周四', '周五', '周六'][value]
    }
    if (result.length > 0 && value < 10) {
      value = '0' + value
    }
    return value || 0
  })
  // console.log('resultString', resultString)
  return resultString
}

/**
 * 根据固定 yyyy-MM-dd 格式的日期字符串以及指定的返回类型返回该日期的年月日
 * 例如：getYMD('2022-10-25', 'y') 返回 '2022'
 * @param {String}  dateString yyyy-MM-dd格式的日期字符串
 * @param {String}  type 返回类型，年y、月m、日d
 * @return {String|Number}
 **/
export function getYMD(dateString, type) {
  if (!dateString || dateString === '') return ''
  const a = dateString.split('-')
  if (a.length !== 3) return ''
  switch (type) {
    case 'y':
      return a[0]
    case 'm':
      return a[1]
    case 'd':
      return a[2]
    default:
      return ''
  }
}

/**
 * 得到本月的开始日期
 * @return {String} yyyy-MM-dd格式的日期字符串
 */
export function getNowMonthStart() {
  return obj2Str(new Date(), '{y}-{m}-{d}')
}

/**
 * 传入一个 yyyy-MM-dd 格式的日期，计算得到和这个日期相差指定间隔类型的时间长度的新日期
 * @param {String}  dateString 要计算的 yyyy-MM-dd 格式的日期
 * @param {String}  interval 间隔长度，年y、月m、日d
 * @param {String}  type 间隔类型，年y、月m、日d
 * @return {String} yyyy-MM-dd格式的日期字符串
 */
export function getDateAfterInterval(dateString, interval, type) {
  // 只支持年、月、日三种类型
  let validTypes = ['y', 'm', 'd']
  if (!validTypes.includes(type)) {
    throw new Error(`无效参数'${type}'，只允许'y', 'm', 'd'`)
  }
  // 验证指定日期字符串格式是否正确
  if (!isDTStr(dateString)) {
    return ''
  }
  let date = new Date(dateString)
  let year = date.getFullYear()
  // getMonth() 方法返回表示月份的数字
  // 返回值是 0（一月） 到 11（十二月） 之间的一个整数。注意： 一月为 0, 二月为 1, 以此类推。
  let month = date.getMonth()
  let day = date.getDate()

  switch (type) {
    case 'y':
      year += interval
      break
    case 'm':
      // 先计算有几个完整年
      year += Math.floor((month + interval) / 12)
      // 再计算剩下几个月
      month = (month + interval) % 12
      break
    case 'd':
      // 一天的毫秒数
      let millisecondsPerDay = 86400000
      let millisecondsToAdd = interval * millisecondsPerDay
      date = new Date(date.getTime() + millisecondsToAdd)
      year = date.getFullYear()
      month = date.getMonth()
      day = date.getDate()
      break
  }

  // 组装新日期字符串
  let newMonth = String(month + 1).padStart(2, '0')
  let newDay = String(day).padStart(2, '0')
  return `${year}-${newMonth}-${newDay}`
}

/**
 * 得到过去多少天的文字数组，用于echarts横坐标文字显示
 * @param {String}  days 过去多少天
 * @return {Array} MM-dd 格式的日期字符串数组
 */
export function getPastDayTxtArray(days) {
  const aryReturn = []
  const now = new Date()
  let month, day
  for (var i = 0; i < days; i++) {
    // 得到前1,2,3...30天的日期
    now.setDate(now.getDate() - 1)
    month = now.getMonth() + 1
    month = month < 10 ? '0' + month : month
    day = now.getDate()
    day = day < 10 ? '0' + day : day
    aryReturn.push(month + '-' + day)
  }
  return aryReturn
}

/**
 * 得到指定日期间隔内的日期文字数组，用于echarts横坐标文字显示
 * @param {String}  dateStringStart 日期间隔开始日期，yyyy-MM-dd 格式
 * @param {String}  dateStringEnd 日期间隔结束日期，yyyy-MM-dd 格式
 * @return {Array} MM-dd 格式的日期字符串数组
 */
export function getDateTxtArray(dateStringStart, dateStringEnd) {
  const aryReturn = []
  let days = getDaysBetweenDates(dateStringStart, dateStringEnd)
  const now = str2Date(dateStringEnd, 'yyyy-MM-dd')
  now.setDate(now.getDate() + 1)
  let month, day
  for (var i = 0; i < days; i++) {
    // 得到前1,2,3...30天的日期
    now.setDate(now.getDate() - 1)
    month = now.getMonth() + 1
    month = month < 10 ? '0' + month : month
    day = now.getDate()
    day = day < 10 ? '0' + day : day
    aryReturn.push(month + '-' + day)
  }
  return aryReturn
}

/**
 * 得到两个日期之间的间隔天数
 * @param {String}  dateStringStart 日期间隔开始日期字符串，yyyy-MM-dd 格式
 * @param {String}  dateStringEnd 日期间隔结束日期字符串，yyyy-MM-dd 格式
 * @return {Number} 间隔天数
 */
export function getDaysBetweenDates(dateStringStart, dateStringEnd) {
  const dateStart = str2Date(dateStringStart, 'yyyy-MM-dd')
  const dateEnd = str2Date(dateStringEnd, 'yyyy-MM-dd')
  // 一天的毫秒数
  const oneDayMills = 24 * 60 * 60 * 1000
  // Math.abs 返回该值的绝对值
  // 计算两个日期之间的天数差异，并四舍五入为整数
  const diffDays = Math.round(Math.abs((dateEnd - dateStart) / oneDayMills))
  return diffDays + 1
}
